package main

import (
	"bufio"
	"fmt"
	"html"
	"io"
	"io/ioutil"
	"os"
	"regexp"
	"strings"
)

var cookie = `q_c1=70cd27ba1d5b49d5acbfcb4d6b5768df|1594120668000|1594120668000; _zap=0417504e-6d83-4d1e-abb5-c477cfd1231f; d_c0="AKDTjwrciRGPTq2G61dwM1iwCY4_aXQwKrk=|1594089372"; _ga=GA1.2.921176368.1594089374; _xsrf=XDtwVvrmO0ykFl3BELwGkCTJqAyjkdQF; Hm_lvt_98beee57fd2ef70ccdd5ca52b9740c49=1614045554,1614048587,1614235724,1614771839; z_c0="2|1:0|10:1614771848|4:z_c0|92:Mi4xSGlJUUJ3QUFBQUFBb05PUEN0eUpFU2NBQUFDRUFsVk5pQU5uWUFEOC1Bdk9vWXVMclJpWUw1dU5VVjNra2F2WXJB|e21d54299f37d0a82dfbdf07befafca5f4c6ada0b131c261261f53ac263189e8"; tst=r; Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740c49=1614840069; SESSIONID=NGeG2rzRafrygiBD9CxqvQQCouAQqck1CJAJvLMi920; JOID=U14dBUxwfNsj6kZjFXf9SoL6kvANOTWwZd4zF0kXHadUjCkmX3_9lETrT2MaYlwJr-jYuveJ-BGdfaiImisD2nI=; osd=W1gUB054etIh6E5lHHX_QoTzkPIFPzyyZ9Y1HksVFaFdjisuWXb_lkztRmEYaloArerQvP6L-hmbdKqKki0K2HA=; KLBRSID=d1f07ca9b929274b65d830a00cbd719a|1614840075|1614839816`

func main() {
	//err := Book(0)
	//if err != nil {
	//	panic(err)
	//}

	//ii := 0
	//err := ReadFile("zhihu.txt", func(i int, text string) {
	//	//fmt.Println(i)
	//	args := strings.Split(text, " ")
	//	if args[4] != "book" {
	//		return
	//	}
	//
	//	ii++
	//	//if ii !=640 {
	//	//	return
	//	//}
	//	categories, score, err := BookInfo(args[0])
	//	if err != nil {
	//		panic(err)
	//	}
	//
	//	err = Catalog(args[0], 0, ii, args[1], args[2], score, categories)
	//	if err != nil {
	//		panic(err)
	//	}
	//})
	//if err != nil {
	//	panic(err)
	//}

	fileList, err := ioutil.ReadDir("catalog")
	if err != nil {
		panic(err)
	}
	for _, v := range fileList {
		if isExists(fmt.Sprintf("zhihu/%s", v.Name())) {
			continue
		}
		name := strings.Replace(v.Name(), ".txt", "", -1)
		name = name[5:]
		WriteFile(fmt.Sprintf("zhihu/%s", v.Name()), []byte(name))
		ReadFile(fmt.Sprintf("catalog/%s", v.Name()), func(i int, text string) {
			args := strings.Split(text, " ")
			fmt.Println(args)
			title := fmt.Sprintf("\n\n\n\n========================================================================\n"+
				"[%s %s][%s %s](%s)(%s)\n"+
				"========================================================================\n\n",
				args[2], args[3], args[4], args[5], args[6], args[7])
			WriteFile(fmt.Sprintf("zhihu/%s", v.Name()), []byte(title))
			context, err := Context(args[0], args[1])
			if err != nil {
				panic(err)
			}
			WriteFile(fmt.Sprintf("zhihu/%s", v.Name()), []byte(context))

		})
	}
}

func Book(offset int) error {
	limit := 10
	fmt.Println(offset)

	url := fmt.Sprintf("https://api.zhihu.com/market/categories/all?limit=%d&dataType=new&study_type=album&sort_type=hottest&offset=%d&level=2&right_type=", limit, offset)
	json, err := NewRequest().Get(url).SendAndReadToJson()
	if err != nil {
		return err
	}
	datas := json.Get("data")
	for _, data := range datas.([]interface{}) {
		dataJson := NewJsonMap(data.(map[string]interface{}))

		str := fmt.Sprintf("%s %s %s %s %s\n", str(dataJson.Get("business_id")), str(dataJson.Get("title")),
			str(dataJson.Get("author").([]interface{})[0]), str(dataJson.Get("chapter")), str(dataJson.Get("media_type")))
		err = WriteFile("zhihu.txt", []byte(str))
		if err != nil {
			return err
		}
	}
	offset += 10
	if !json.Get("paging.is_end").(bool) {
		return Book(offset)
	}
	return nil
}

func BookInfo(id string) (string, string, error) {
	res, err := NewRequest().Get(fmt.Sprintf("https://www.zhihu.com/xen/market/remix/paid_column/%s", id)).Send()
	if err != nil {
		return "", "", err
	}
	html := res.Body
	cat := str(substr("\"HeaderInfo-desc-pQfW3\">", "</div>", html))
	if len(cat) > 200 {
		cat = ""
	}
	score := str(substr("\"font-family:Number\">", "</span>", html))
	if score == "" {
		score = "未评"
	}
	return cat, score, nil
}

func Catalog(id string, offset int, i int, name, auth, score, category string) error {
	json, err := NewRequest().Get(fmt.Sprintf("https://api.zhihu.com/remix/well/%s/catalog?offset=%d&limit=10&order_by=global_idx&is_new_column=true", id, offset)).SendAndReadToJson()
	if err != nil {
		return err
	}
	datas := json.Get("data")

	for _, data := range datas.([]interface{}) {
		dataJson := NewJsonMap(data.(map[string]interface{}))
		s := fmt.Sprintf("%s %s %s %s %s %s %s %s\n", id, str(dataJson.Get("id")), str(dataJson.Get("chapter.serial_number_txt")),
			str(dataJson.Get("chapter.title")), str(dataJson.Get("index.serial_number_txt")), str(dataJson.Get("title")),
			str(dataJson.Get("meta_v2[0].content")), str(json.Get("extra.update_text")))
		filename := fmt.Sprintf("catalog/%04d.[%s][%s][%s分](%s)(%s).txt", i, category, name, score, auth, str(json.Get("extra.update_text")))
		err = WriteFile(filename, []byte(s))
		if err != nil {
			return err
		}
	}
	offset += 10
	if json.Get("paging.has_next").(bool) {
		return Catalog(id, offset, i, name, auth, score, category)
	}
	return nil
}

func Context(id1, id2 string) (string, error) {
	res, err := NewRequest().Get(fmt.Sprintf("https://www.zhihu.com/market/paid_column/%s/section/%s", id1, id2)).
		Header("cookie", cookie).Send()
	if err != nil {
		return "", err
	}
	html := res.Body
	html = substr("<textarea id=\"resolved\" hidden>", "</textarea>", html)
	j, err := NewJson(html)
	if err != nil {
		return "", err
	}
	html = j.Get("appContext.__connectedAutoFetch.manuscript.data.manuscriptData.manuscript").(string)
	html = trimHtml(html)
	fmt.Println(html)
	return html, nil
}

func WriteFile(filename string, data []byte) error {
	fmt.Print(string(data))
	f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		return err
	}
	n, err := f.Write(data)
	if err == nil && n < len(data) {
		err = io.ErrShortWrite
	}
	if err1 := f.Close(); err == nil {
		err = err1
	}
	return err
}

func ReadFile(filename string, f func(i int, text string)) error {
	file, err := os.Open(filename)
	if err != nil {
		return nil
	}
	defer file.Close()
	i := 0
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		i++
		f(i, scanner.Text())
	}
	return nil
}

func str(v interface{}) string {
	return strings.Trim(strings.ReplaceAll(fmt.Sprintf("%v", v), " ", ""), "\n")
}

func substr(str1, str2, str string) string {
	index1 := strings.Index(str, str1) + len(str1)
	if index1 < 0 {
		return ""
	}
	index2 := strings.Index(str[index1:], str2) + index1
	if index1 < 0 {
		return ""
	}
	return str[index1:index2]
}

func trimHtml(src string) string {
	//将HTML标签全转换成小写
	re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
	src = re.ReplaceAllStringFunc(src, strings.ToLower)
	//去除STYLE
	re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
	src = re.ReplaceAllString(src, "")
	//去除SCRIPT
	re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
	src = re.ReplaceAllString(src, "")
	//去除所有尖括号内的HTML代码，并换成换行符
	re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
	src = re.ReplaceAllString(src, "")
	//去除连续的换行符
	re, _ = regexp.Compile("\\s{2,}")
	src = re.ReplaceAllString(src, "\n")
	return html.UnescapeString(strings.TrimSpace(src))
}

func isExists(path string) bool {
	_, err := os.Stat(path)
	if err == nil {
		return true
	}
	if os.IsNotExist(err) {
		return false
	}
	return false
}
